const compiler = function compiler() {
    console.log('视图编译更新');
};

// 重构数组的原型
let proto = {};
Object.setPrototypeOf(proto, Array.prototype);
['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(name => {
    Object.defineProperty(proto, name, {
        value(...params) {
            // 依然基于数组内置方法实现相关的功能
            Array.prototype[name].call(this, ...params);
            // 处理完毕后通知视图更新即可
            compiler();
        }
    });
});

// 响应式数据的核心处理
const observer = function observer(obj) {
    let isArray = Array.isArray(obj),
        isObject = _.isPlainObject(obj);
    if (!isArray && !isObject) return obj;
    // 数组：重定向原型指向
    if (isArray) {
        Object.setPrototypeOf(obj, proto);
        _.each(obj, item => observer(item));
        return obj;
    }
    // 对象：给每一个成员做数据劫持
    let proxy = { ...obj };
    _.each(obj, (value, key) => {
        Object.defineProperty(obj, key, {
            get() {
                return proxy[key];
            },
            set(val) {
                if (val === value) return;
                proxy[key] = val;
                // 通知视图更新
                compiler();
            }
        });
        observer(value);
    });
    return obj;
};

// 测试结果
let data = {
    msg: '你好,世界!',
    num: 10,
    obj: {
        x: 100,
        y: 200,
        z: [10, 20, 30]
    },
    arr: [100, 200, { n: 0, m: 1 }]
};
observer(data);